#include <sys/types.h>
#include <sys/stat.h>
#include <string.h>
#include <stdio.h>
#include <fcntl.h>
#include <errno.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <assert.h>
#include <linux/i2c.h>
#include <linux/i2c-dev.h>
#include <linux/types.h>

int higher2lower(char c);
int htoi(char s[]);

#define MSB_0_7_OF_U32(DATA) ((DATA >> 24) & 0xFF)
#define MSB_8_15_OF_U32(DATA) ((DATA >> 16) & 0xFF)
#define MSB_16_23_OF_U32(DATA) ((DATA >> 8) & 0xFF)
#define MSB_24_31_OF_U32(DATA) ((DATA >> 0) & 0xFF)
#define REG_VAL_32_BIT(VAL_8_BIT_0, VAL_8_BIT_1, VAL_8_BIT_2, VAL_8_BIT_3) \
		((VAL_8_BIT_0 << 24) | (VAL_8_BIT_1 << 16) | (VAL_8_BIT_2 << 8) | VAL_8_BIT_3)

//this is i2c 10bit

int main()
{
	int fd, i, j, ret;
	char *errorinfo;
	struct i2c_rdwr_ioctl_data work_queue;
	unsigned int i2c_adaptor, slave_address, reg_address, byte_count, reg_val, format_nms3210, reg_num, rw_flag;
	unsigned char val;
	unsigned int value[2];

//	access_tran access;
	i2c_adaptor =0;
	slave_address = 0x2;
	reg_address =0x158;
	reg_val = 0;
	rw_flag = 0;
	value[1]=slave_address&0xff;
	value[0]=((slave_address&0x300)>>8)|0x78;
	printf("i2c_adaptor : %#x\nslave_address : %#x\nreg_address : %#x\nreg_val : %#x\nrw_flag : %#x\n", \
				i2c_adaptor, slave_address, reg_address, reg_val, rw_flag);



	fd = open("/dev/i2c-0", O_RDWR);
	if(!fd)
	{
		printf("Error on opening the device file\n");
		return 0;
	}

	//IIC configuration
	ioctl(fd, I2C_TIMEOUT, 2);
	ioctl(fd, I2C_RETRIES, 1);

	/*
	 * IIC operation
	 * rw_flag = 1; READ
	 * rw_flag = 0; WRITE
	 */
	if(rw_flag)
	{
		work_queue.nmsgs = 2;
		work_queue.msgs = (struct i2c_msg *)malloc(work_queue.nmsgs * sizeof(struct i2c_msg));

		if(!work_queue.msgs)
		{
			printf("memory alloc error\n");
			close(fd);
			return 0;
		}

		reg_num = 1;
		format_nms3210 = (rw_flag << 31) | ((reg_num - 1) << 22) | (reg_address >> 2);
		printf("format_nms3210 : %#x\n", format_nms3210);
		(work_queue.msgs[0]).len = 5;
		(work_queue.msgs[0]).addr = value[0];
		(work_queue.msgs[0]).flags = 0;//w
		(work_queue.msgs[0]).buf = (unsigned char *)malloc(5);
		(work_queue.msgs[0]).buf[0]=value[1];
		(work_queue.msgs[0]).buf[1] = MSB_0_7_OF_U32(format_nms3210);
		(work_queue.msgs[0]).buf[2] = MSB_8_15_OF_U32(format_nms3210);
		(work_queue.msgs[0]).buf[3] = MSB_16_23_OF_U32(format_nms3210);
		(work_queue.msgs[0]).buf[4] = MSB_24_31_OF_U32(format_nms3210);

		(work_queue.msgs[1]).len = 4;
		(work_queue.msgs[1]).flags = I2C_M_RD;//R
		(work_queue.msgs[1]).addr = value[0];
		(work_queue.msgs[1]).buf = (unsigned char *)malloc(4);

		ret = ioctl(fd, I2C_RDWR, (unsigned long)&work_queue);
		reg_val = REG_VAL_32_BIT(work_queue.msgs[1].buf[0], work_queue.msgs[1].buf[1], \
						work_queue.msgs[1].buf[2], work_queue.msgs[1].buf[3]);
		if(ret < 0)
		  printf("error code : %d\n", ret);
		else
		  printf("slave_addr : %#x  reg_addr : %#x  reg_val : %#x\n", slave_address, reg_address, reg_val);
		free(work_queue.msgs);
	}
	else
	{
		work_queue.nmsgs = 1;
		work_queue.msgs = (struct i2c_msg *)malloc(work_queue.nmsgs * sizeof(struct i2c_msg));
		printf("work_queue.msgs addr* : %#x\n", (unsigned int*)work_queue.msgs);

		if(!work_queue.msgs)
		{
			printf("memory alloc error\n");
			close(fd);
			return 0;
		}
		reg_num = 1;
		format_nms3210 = (rw_flag << 31) | ((reg_num - 1) << 22) | (reg_address >> 2);
		printf("format_nms3210 : %#x\n", format_nms3210);
		(work_queue.msgs[0]).len = 9;//reg_addr 4 + reg_val 4
		(work_queue.msgs[0]).addr = value[0];
		(work_queue.msgs[0]).flags = 0;//w
		(work_queue.msgs[0]).buf = (unsigned char *)malloc(9);
		(work_queue.msgs[0]).buf[0]=value[1];
		(work_queue.msgs[0]).buf[1] = 0x00;
		(work_queue.msgs[0]).buf[2] = 0x00;
		(work_queue.msgs[0]).buf[3] = 0x00;
		(work_queue.msgs[0]).buf[4] = 0x1B;

		(work_queue.msgs[0]).buf[5] = MSB_0_7_OF_U32(reg_val);
		(work_queue.msgs[0]).buf[6] = MSB_8_15_OF_U32(reg_val);
		(work_queue.msgs[0]).buf[7] = MSB_16_23_OF_U32(reg_val);
		(work_queue.msgs[0]).buf[8] = MSB_24_31_OF_U32(reg_val);


		ret = ioctl(fd, I2C_RDWR, (unsigned long)&work_queue);
		if(ret < 0)
		  printf("error code : %d\n", ret);
		free(work_queue.msgs);
	}

	close(fd);
	return ret;
}

int higher2lower(char c)
{
	if(c >= 'A' && c <= 'Z')
		return c + 'a' - 'A';
	else
	  return c;
}

int htoi(char s[])
{
	int i;
	int n = 0;
	if(s[0] == '0' && (s[1] == 'x' || s[1] == 'x'))
	  i = 2;
	else
	  i = 0;

//	if((s[i] >= '0' && s[i] <= '9') || (s[i] >= 'a' && s[i] <= 'f') \
			|| (s[i] >= 'A' && s[i] <= 'F'))
//	{
	for(;(s[i] >= '0' && s[i] <= '9') || (s[i] >= 'a' && s[i] <= 'f') \
			|| (s[i] >= 'A' && s[i] <= 'F'); ++i)
	{
		if(higher2lower(s[i] > '9'))
		{
			n = 16 * n +(10 + higher2lower(s[i]) - 'a');
		}
		else
		  n = 16 * n + (higher2lower(s[i] - '0'));
	}
//	}
	return n;
}
